package model

import (
	"time"

	"gddgame.cc/galaxy/common/dsl/game"
	"gddgame.cc/galaxy/common/dsl/game/language"
	"gddgame.cc/galaxy/common/dsl/game/skill"
	"gddgame.cc/galaxy/common/dsl/game/sync"
	"gddgame.cc/galaxy/common/namespaces/cooperate/structure"
	"gddgame.cc/galaxy/utils/orm"
)

type ModelData struct {
	Maps     []Map
	MapMap   map[int]*Map
	MapNos   []MapNo
	MapNoMap map[string]*MapNo

	DefineBuilds        []DefineBuild
	DefineBuildLevels   []DefineBuildLevel
	DefineBuildLevelMap map[int][]*DefineBuildLevel

	DefineUnits        []DefineUnit
	DefineUnitLevels   []DefineUnitLevel
	DefineUnitLevelMap map[int][]*DefineUnitLevel

	DefineNodes []DefineNode
	DefineItems []DefineItem

	SettingMessages        []SettingMessage
	SettingMessageMap      map[string]*SettingMessage
	SettingDirects         []SettingDirect
	SettingDirectMap       map[int]*SettingDirect
	SettingOperations      []SettingOperation
	SettingOperationMap    map[int]*SettingOperation
	SettingEquips          []SettingEquip
	SettingEquipLevels     []SettingEquipLevel
	SettingEquipLevelMap   map[int][]*SettingEquipLevel
	SettingPowers          []SettingPower
	SettingPowerLevels     []SettingPowerLevel
	SettingPowerLevelMap   map[int][]*SettingPowerLevel
	SettingProps           []SettingProp
	SettingSciences        []SettingScience
	SettingScienceLevels   []SettingScienceLevel
	SettingScienceLevelMap map[int][]*SettingScienceLevel
	SettingShopProps       []SettingShopProp

	defineBuildModel      *orm.Model
	defineBuildLevelModel *orm.Model
	defineUnitModel       *orm.Model
	defineUnitLevelModel  *orm.Model
	defineNodeModel       *orm.Model
	defineItemModel       *orm.Model

	settingMessageModel      *orm.Model
	settingDirectModel       *orm.Model
	settingOperationModel    *orm.Model
	settingEquipModel        *orm.Model
	settingEquipLevelModel   *orm.Model
	settingPowerModel        *orm.Model
	settingPowerLevelModel   *orm.Model
	settingPropModel         *orm.Model
	settingScienceModel      *orm.Model
	settingScienceLevelModel *orm.Model
	settingShopPropModel     *orm.Model

	BuildList []*Build
	BuildMap  map[int]*Build
	UnitList  []*Unit
	UnitMap   map[int]*Unit
	NodeList  []*Node
	NodeMap   map[int]*Node
	ItemList  []*Item
	ItemMap   map[int]*Item

	DirectList    []*Direct
	OperationList []*Operation
	EquipList     []*Equip
	PowerList     []*Power
	ScienceList   []*Science
	PropList      []*Prop
	PropMap       map[int]*Prop
	ShopPropMap   map[int]*ShopProp
	ShopPropList  map[string][]*ShopProp

	DirectMap        map[int]*Direct
	OperationMap     map[int]*Operation
	ScienceMap       map[int]*Science
	ScienceTargetMap map[structure.PublicDataType]map[int]map[int]*Science
	EquipMap         map[int]*Equip
	PowerMap         map[int]*Power

	// 逻辑限定了，一个指令赋予一个道具，只保存有指令效果的道具
	// 并且一个道具最多只有一个指令
	PropWithDirectMap map[int]*Prop

	// 部队可建
	UnitBuilds  []*Build
	CreateUnits []*Unit

	PersistenceMap map[string]bool
}

var (
	DefaultModelData *ModelData
	DefaultSkillData *skill.SkillData
)

func GetModelData(env *game.Environment, language *language.LanguageData, syncData *sync.SyncData) (*ModelData, error) {
	var err error
	data := &ModelData{}

	buildProvider := &game.DataProvider{
		Name:     "build",
		Array:    true,
		Language: true,
		Get: func() (i interface{}, err error) {
			return data.BuildList, nil
		},
	}
	env.RegisterData(buildProvider)
	unitProvider := &game.DataProvider{
		Name:     "unit",
		Array:    true,
		Language: true,
		Get: func() (i interface{}, err error) {
			return data.UnitList, nil
		},
	}
	env.RegisterData(unitProvider)
	nodeProvider := &game.DataProvider{
		Name:  "node",
		Array: true,
		Get: func() (i interface{}, err error) {
			return data.NodeList, nil
		},
	}
	env.RegisterData(nodeProvider)
	itemProvider := &game.DataProvider{
		Name:  "item",
		Array: true,
		Get: func() (i interface{}, err error) {
			return data.ItemList, nil
		},
	}
	env.RegisterData(itemProvider)
	directProvider := &game.DataProvider{
		Name:     "direct",
		Array:    true,
		Language: true,
		Get: func() (i interface{}, err error) {
			return data.DirectList, nil
		},
	}
	env.RegisterData(directProvider)
	operationProvider := &game.DataProvider{
		Name:     "operation",
		Array:    false,
		Language: true,
		Get: func() (i interface{}, err error) {
			return data.OperationList, nil
		},
	}
	env.RegisterData(operationProvider)
	equipProvider := &game.DataProvider{
		Name:     "equip",
		Array:    true,
		Language: true,
		Get: func() (i interface{}, err error) {
			return data.EquipList, nil
		},
	}
	env.RegisterData(equipProvider)
	powerProvider := &game.DataProvider{
		Name:     "power",
		Array:    true,
		Language: true,
		Get: func() (i interface{}, err error) {
			return data.PowerList, nil
		},
	}
	env.RegisterData(powerProvider)
	scienceProvider := &game.DataProvider{
		Name:     "science",
		Array:    true,
		Language: true,
		Get: func() (i interface{}, err error) {
			return data.ScienceList, nil
		},
	}
	env.RegisterData(scienceProvider)
	propProvider := &game.DataProvider{
		Name:     "prop",
		Array:    true,
		Language: true,
		Get: func() (i interface{}, err error) {
			return data.PropList, nil
		},
	}
	env.RegisterData(propProvider)

	if _, data.Maps, data.MapMap, err = getMapData(env); err != nil {
		return nil, err
	}
	if _, data.MapNos, data.MapNoMap, err = getMapNoData(env); err != nil {
		return nil, err
	}
	if data.defineBuildModel, data.DefineBuilds, err = getDefineBuildData(env); err != nil {
		return nil, err
	}
	if data.defineBuildLevelModel, data.DefineBuildLevels, data.DefineBuildLevelMap, err = getDefineBuildLevelData(env); err != nil {
		return nil, err
	}
	if data.defineUnitModel, data.DefineUnits, err = getDefineUnitData(env); err != nil {
		return nil, err
	}
	if data.defineUnitLevelModel, data.DefineUnitLevels, data.DefineUnitLevelMap, err = getDefineUnitLevelData(env); err != nil {
		return nil, err
	}
	if data.defineNodeModel, data.DefineNodes, err = getDefineNodeData(env, nodeProvider); err != nil {
		return nil, err
	}
	if data.defineItemModel, data.DefineItems, err = getDefineItemData(env, itemProvider); err != nil {
		return nil, err
	}

	if data.settingMessageModel, data.SettingMessages, data.SettingMessageMap, err = getSettingMessageData(env); err != nil {
		return nil, err
	}
	if data.settingDirectModel, data.SettingDirects, data.SettingDirectMap, err = getSettingDirectData(env); err != nil {
		return nil, err
	}
	if data.settingOperationModel, data.SettingOperations, data.SettingOperationMap, err = getSettingOperationData(env); err != nil {
		return nil, err
	}
	if data.settingEquipModel, data.SettingEquips, err = getSettingEquipData(env); err != nil {
		return nil, err
	}
	if data.settingEquipLevelModel, data.SettingEquipLevels, data.SettingEquipLevelMap, err = getSettingEquipLevelData(env); err != nil {
		return nil, err
	}
	if data.settingPowerModel, data.SettingPowers, err = getSettingPowerData(env); err != nil {
		return nil, err
	}
	if data.settingPowerLevelModel, data.SettingPowerLevels, data.SettingPowerLevelMap, err = getSettingPowerLevelData(env); err != nil {
		return nil, err
	}
	if data.settingScienceModel, data.SettingSciences, err = getSettingScienceData(env); err != nil {
		return nil, err
	}
	if data.settingScienceLevelModel, data.SettingScienceLevels, data.SettingScienceLevelMap, err = getSettingScienceLevelData(env); err != nil {
		return nil, err
	}
	if data.settingPropModel, data.SettingProps, err = getSettingPropData(env); err != nil {
		return nil, err
	}
	if data.settingShopPropModel, data.SettingShopProps, err = getSettingShopPropData(env); err != nil {
		return nil, err
	}

	data.PersistenceMap = map[string]bool{}

	data.BuildList = make([]*Build, len(data.DefineBuilds))
	data.BuildMap = make(map[int]*Build, len(data.DefineBuilds))
	data.UnitBuilds = []*Build{}
	for key := range data.DefineBuilds {
		build := &data.DefineBuilds[key]
		data.BuildList[key] = NewBuild(syncData, language, buildProvider, build, data.DefineBuildLevelMap[build.Id])
		data.BuildMap[build.Id] = data.BuildList[key]
		if build.CanUnit {
			data.UnitBuilds = append(data.UnitBuilds, data.BuildList[key])
		}
		for _, item := range build.SyncKeys {
			data.PersistenceMap[item] = true
		}
	}
	data.UnitList = make([]*Unit, len(data.DefineUnits))
	data.UnitMap = make(map[int]*Unit, len(data.DefineUnits))
	data.CreateUnits = []*Unit{}
	for key := range data.DefineUnits {
		unit := &data.DefineUnits[key]
		data.UnitList[key] = NewUnit(syncData, language, unitProvider, unit, data.DefineUnitLevelMap[unit.Id])
		data.UnitMap[unit.Id] = data.UnitList[key]
		if unit.CanCreate {
			data.CreateUnits = append(data.CreateUnits, data.UnitList[key])
		}
		for _, item := range unit.SyncKeys {
			data.PersistenceMap[item] = true
		}
	}
	data.ItemList = make([]*Item, len(data.DefineItems))
	data.ItemMap = make(map[int]*Item, len(data.DefineItems))
	for key := range data.DefineItems {
		item := &data.DefineItems[key]
		data.ItemList[key] = NewItem(syncData, itemProvider, item)
		data.ItemMap[item.Id] = data.ItemList[key]
		for _, item := range item.SyncKeys {
			data.PersistenceMap[item] = true
		}
	}
	data.NodeList = make([]*Node, len(data.DefineNodes))
	data.NodeMap = make(map[int]*Node, len(data.DefineNodes))
	for key := range data.DefineNodes {
		node := &data.DefineNodes[key]
		data.NodeList[key] = NewNode(syncData, nodeProvider, node)
		data.NodeMap[node.Id] = data.NodeList[key]
		for _, item := range node.SyncKeys {
			data.PersistenceMap[item] = true
		}
	}
	data.EquipList = make([]*Equip, len(data.SettingEquips))
	data.EquipMap = make(map[int]*Equip, len(data.SettingEquips))
	for key := range data.SettingEquips {
		equip := &data.SettingEquips[key]
		data.EquipList[key] = NewEquip(language, equipProvider, equip, data.SettingEquipLevelMap[equip.Id])
		data.EquipMap[equip.Id] = data.EquipList[key]
	}
	data.PowerList = make([]*Power, len(data.SettingPowers))
	data.PowerMap = make(map[int]*Power, len(data.SettingPowers))
	for key := range data.SettingPowers {
		power := &data.SettingPowers[key]
		data.PowerList[key] = NewPower(language, powerProvider, power, data.SettingPowerLevelMap[power.Id])
		data.PowerMap[power.Id] = data.PowerList[key]
	}
	data.ScienceList = make([]*Science, len(data.SettingSciences))
	data.ScienceMap = make(map[int]*Science, len(data.SettingSciences))
	data.ScienceTargetMap = map[structure.PublicDataType]map[int]map[int]*Science{}
	for key := range data.SettingSciences {
		science := &data.SettingSciences[key]
		data.ScienceList[key] = NewScience(language, scienceProvider, science, data.SettingScienceLevelMap[science.Id])
		data.ScienceMap[science.Id] = data.ScienceList[key]
		for _, level := range data.ScienceList[key].Levels {
			for dataType, pm := range level.TargetEffectSlice {
				if _, ok := data.ScienceTargetMap[dataType]; !ok {
					data.ScienceTargetMap[dataType] = map[int]map[int]*Science{}
				}
				keyMap := data.ScienceTargetMap[dataType]
				for id, _ := range pm {
					if _, ok := keyMap[id]; !ok {
						keyMap[id] = map[int]*Science{}
					}
					scienceMap := keyMap[id]
					if _, ok := scienceMap[science.Id]; !ok {
						scienceMap[science.Id] = data.ScienceList[key]
					}
				}

			}
		}
	}
	data.DirectList = make([]*Direct, len(data.SettingDirects))
	data.DirectMap = make(map[int]*Direct, len(data.SettingDirects))
	for key := range data.SettingDirects {
		direct := &data.SettingDirects[key]
		data.DirectList[key] = NewDirect(language, directProvider, direct)
		data.DirectMap[direct.Id] = data.DirectList[key]
	}
	data.OperationList = make([]*Operation, len(data.SettingOperations))
	data.OperationMap = make(map[int]*Operation, len(data.SettingOperations))
	for key := range data.SettingOperations {
		operation := &data.SettingOperations[key]
		data.OperationList[key] = NewOperation(operationProvider, operation)
		data.OperationMap[operation.Id] = data.OperationList[key]
	}
	data.PropList = make([]*Prop, len(data.SettingProps))
	data.PropMap = make(map[int]*Prop, len(data.SettingProps))
	data.PropWithDirectMap = map[int]*Prop{}
	for key := range data.SettingProps {
		prop := &data.SettingProps[key]
		data.PropList[key] = NewProp(language, propProvider, prop)
		data.PropMap[prop.Id] = data.PropList[key]
		if len(data.PropList[key].EffectSlice.DirectIds) > 0 {
			for _, id := range data.PropList[key].EffectSlice.DirectIds {
				data.PropWithDirectMap[id] = data.PropList[key]
			}
		}
	}
	data.ShopPropList = make(map[string][]*ShopProp)
	data.ShopPropMap = map[int]*ShopProp{}
	for key := range data.SettingShopProps {
		shopProp := &data.SettingShopProps[key]
		data.ShopPropMap[shopProp.Id] = NewShopProp(shopProp, data.PropList[shopProp.PropId])
		if _, ok := data.ShopPropList[shopProp.Area]; !ok {
			data.ShopPropList[shopProp.Area] = []*ShopProp{}
		}
		data.ShopPropList[shopProp.Area] = append(data.ShopPropList[shopProp.Area], data.ShopPropMap[shopProp.Id])
	}

	return data, nil
}
func getMapData(env *game.Environment) (*orm.Model, []Map, map[int]*Map, error) {
	var err error
	model, err := env.GetModel(MapName)
	if err != nil {
		return nil, nil, nil, err
	}
	var maps []Map
	_, err = model.Query().Find(&maps)
	if err != nil {
		return nil, nil, nil, err
	}
	mapMap := make(map[int]*Map)
	for key := range maps {
		mapMap[maps[key].Id] = &maps[key]
	}
	return model, maps, mapMap, nil
}
func getMapNoData(env *game.Environment) (*orm.Model, []MapNo, map[string]*MapNo, error) {
	var err error
	model, err := env.GetModel(MapNoName)
	if err != nil {
		return nil, nil, nil, err
	}
	var mapNos []MapNo
	_, err = model.Query().Find(&mapNos)
	if err != nil {
		return nil, nil, nil, err
	}
	mapNoMap := make(map[string]*MapNo)
	for key := range mapNos {
		mapNoMap[mapNos[key].Id] = &mapNos[key]
	}
	return model, mapNos, mapNoMap, nil
}

func getDefineBuildLevelData(env *game.Environment) (*orm.Model, []DefineBuildLevel, map[int][]*DefineBuildLevel, error) {
	var err error
	model, err := env.GetModel(DefineBuildLevelName)
	if err != nil {
		return nil, nil, nil, err
	}
	var levels []DefineBuildLevel
	_, err = model.Query().Order("build_id", orm.ASC).Order("level", orm.ASC).Find(&levels)
	if err != nil {
		return nil, nil, nil, err
	}
	Levels := make(map[int][]*DefineBuildLevel)
	for key := range levels {
		l := &levels[key]
		if _, ok := Levels[l.BuildId]; !ok {
			Levels[l.BuildId] = []*DefineBuildLevel{}
		}
		list := Levels[l.BuildId]
		if l.Level >= len(list) {
			list = append(list, make([]*DefineBuildLevel, l.Level+1-len(list))...)
			Levels[l.BuildId] = list
		}
		list[l.Level] = l
	}
	return model, levels, Levels, nil
}
func getDefineBuildData(env *game.Environment) (*orm.Model, []DefineBuild, error) {
	var err error
	model, err := env.GetModel(DefineBuildName)
	if err != nil {
		return nil, nil, err
	}
	var builds []DefineBuild
	_, err = model.Query().Find(&builds)
	if err != nil {
		return nil, nil, err
	}
	return model, builds, nil
}

func getDefineUnitLevelData(env *game.Environment) (*orm.Model, []DefineUnitLevel, map[int][]*DefineUnitLevel, error) {
	var err error
	model, err := env.GetModel(DefineUnitLevelName)
	if err != nil {
		return nil, nil, nil, err
	}
	var levels []DefineUnitLevel
	_, err = model.Query().Order("unit_id", orm.ASC).Order("level", orm.ASC).Find(&levels)
	if err != nil {
		return nil, nil, nil, err
	}
	Levels := make(map[int][]*DefineUnitLevel)
	for key := range levels {
		l := &levels[key]
		if _, ok := Levels[l.UnitId]; !ok {
			Levels[l.UnitId] = []*DefineUnitLevel{}
		}
		list := Levels[l.UnitId]
		if l.Level >= len(list) {
			list = append(list, make([]*DefineUnitLevel, l.Level+1-len(list))...)
			Levels[l.UnitId] = list
		}
		list[l.Level] = l
	}
	return model, levels, Levels, nil
}
func getDefineUnitData(env *game.Environment) (*orm.Model, []DefineUnit, error) {
	var err error
	model, err := env.GetModel(DefineUnitName)
	if err != nil {
		return nil, nil, err
	}
	var units []DefineUnit
	_, err = model.Query().Find(&units)
	if err != nil {
		return nil, nil, err
	}
	return model, units, nil
}

func getDefineNodeData(env *game.Environment, provider *game.DataProvider) (*orm.Model, []DefineNode, error) {
	var err error
	model, err := env.GetModel(DefineNodeName)
	if err != nil {
		return nil, nil, err
	}
	var nodes []DefineNode
	_, err = model.Query().Find(&nodes)
	if err != nil {
		return nil, nil, err
	}
	return model, nodes, nil
}
func getDefineItemData(env *game.Environment, provider *game.DataProvider) (*orm.Model, []DefineItem, error) {
	var err error
	model, err := env.GetModel(DefineItemName)
	if err != nil {
		return nil, nil, err
	}
	var items []DefineItem
	_, err = model.Query().Find(&items)
	if err != nil {
		return nil, nil, err
	}
	return model, items, nil
}
func getSettingMessageData(env *game.Environment) (*orm.Model, []SettingMessage, map[string]*SettingMessage, error) {
	var err error
	model, err := env.GetModel(SettingMessageName)
	if err != nil {
		return nil, nil, nil, err
	}
	var messages []SettingMessage
	_, err = model.Query().Find(&messages)
	if err != nil {
		return nil, nil, nil, err
	}
	MessageMap := make(map[string]*SettingMessage, len(messages))
	for key := range messages {
		message := &messages[key]
		MessageMap[message.Key] = message
	}
	return model, messages, MessageMap, nil
}
func getSettingDirectData(env *game.Environment) (*orm.Model, []SettingDirect, map[int]*SettingDirect, error) {
	var err error
	model, err := env.GetModel(SettingDirectName)
	if err != nil {
		return nil, nil, nil, err
	}
	var directs []SettingDirect
	_, err = model.Query().Find(&directs)
	if err != nil {
		return nil, nil, nil, err
	}
	DirectMap := make(map[int]*SettingDirect, len(directs))
	for key := range directs {
		direct := &directs[key]
		DirectMap[direct.Id] = direct
	}
	return model, directs, DirectMap, nil
}
func getSettingOperationData(env *game.Environment) (*orm.Model, []SettingOperation, map[int]*SettingOperation, error) {
	var err error
	model, err := env.GetModel(SettingOperationName)
	if err != nil {
		return nil, nil, nil, err
	}
	var operations []SettingOperation
	_, err = model.Query().Find(&operations)
	if err != nil {
		return nil, nil, nil, err
	}
	OperationMap := make(map[int]*SettingOperation, len(operations))
	for key := range operations {
		operation := &operations[key]
		OperationMap[operation.Id] = operation
	}
	return model, operations, OperationMap, nil
}

func getSettingEquipData(env *game.Environment) (*orm.Model, []SettingEquip, error) {
	var err error
	model, err := env.GetModel(SettingEquipName)
	if err != nil {
		return nil, nil, err
	}
	var equips []SettingEquip
	_, err = model.Query().Find(&equips)
	if err != nil {
		return nil, nil, err
	}
	return model, equips, nil
}
func getSettingEquipLevelData(env *game.Environment) (*orm.Model, []SettingEquipLevel, map[int][]*SettingEquipLevel, error) {
	var err error
	model, err := env.GetModel(SettingEquipLevelName)
	if err != nil {
		return nil, nil, nil, err
	}
	var levels []SettingEquipLevel
	_, err = model.Query().Order("equip_id", orm.ASC).Order("level", orm.ASC).Find(&levels)
	if err != nil {
		return nil, nil, nil, err
	}
	Levels := make(map[int][]*SettingEquipLevel)
	for key := range levels {
		l := &levels[key]
		if _, ok := Levels[l.EquipId]; !ok {
			Levels[l.EquipId] = []*SettingEquipLevel{}
		}
		list := Levels[l.EquipId]
		if l.Level >= len(list) {
			list = append(list, make([]*SettingEquipLevel, l.Level+1-len(list))...)
			Levels[l.EquipId] = list
		}
		list[l.Level] = l
	}
	return model, levels, Levels, nil
}

func getSettingPowerData(env *game.Environment) (*orm.Model, []SettingPower, error) {
	var err error
	model, err := env.GetModel(SettingPowerName)
	if err != nil {
		return nil, nil, err
	}
	var powers []SettingPower
	_, err = model.Query().Find(&powers)
	if err != nil {
		return nil, nil, err
	}
	return model, powers, nil
}
func getSettingPowerLevelData(env *game.Environment) (*orm.Model, []SettingPowerLevel, map[int][]*SettingPowerLevel, error) {
	var err error
	model, err := env.GetModel(SettingPowerLevelName)
	if err != nil {
		return nil, nil, nil, err
	}
	var levels []SettingPowerLevel
	_, err = model.Query().Order("power_id", orm.ASC).Order("level", orm.ASC).Find(&levels)
	if err != nil {
		return nil, nil, nil, err
	}
	Levels := make(map[int][]*SettingPowerLevel)
	for key := range levels {
		l := &levels[key]
		if _, ok := Levels[l.PowerId]; !ok {
			Levels[l.PowerId] = []*SettingPowerLevel{}
		}
		list := Levels[l.PowerId]
		if l.Level >= len(list) {
			list = append(list, make([]*SettingPowerLevel, l.Level+1-len(list))...)
			Levels[l.PowerId] = list
		}
		list[l.Level] = l
	}
	return model, levels, Levels, nil
}
func getSettingScienceData(env *game.Environment) (*orm.Model, []SettingScience, error) {
	var err error
	model, err := env.GetModel(SettingScienceName)
	if err != nil {
		return nil, nil, err
	}
	var sciences []SettingScience
	_, err = model.Query().Find(&sciences)
	if err != nil {
		return nil, nil, err
	}
	return model, sciences, nil
}
func getSettingScienceLevelData(env *game.Environment) (*orm.Model, []SettingScienceLevel, map[int][]*SettingScienceLevel, error) {
	var err error
	model, err := env.GetModel(SettingScienceLevelName)
	if err != nil {
		return nil, nil, nil, err
	}
	var levels []SettingScienceLevel
	_, err = model.Query().Order("science_id", orm.ASC).Order("level", orm.ASC).Find(&levels)
	if err != nil {
		return nil, nil, nil, err
	}
	Levels := make(map[int][]*SettingScienceLevel)
	for key := range levels {
		l := &levels[key]
		if _, ok := Levels[l.ScienceId]; !ok {
			Levels[l.ScienceId] = []*SettingScienceLevel{}
		}
		list := Levels[l.ScienceId]
		if l.Level >= len(list) {
			list = append(list, make([]*SettingScienceLevel, l.Level+1-len(list))...)
			Levels[l.ScienceId] = list
		}
		list[l.Level] = l
	}
	return model, levels, Levels, nil
}
func getSettingPropData(env *game.Environment) (*orm.Model, []SettingProp, error) {
	var err error
	model, err := env.GetModel(SettingPropName)
	if err != nil {
		return nil, nil, err
	}
	var props []SettingProp
	_, err = model.Query().Find(&props)
	if err != nil {
		return nil, nil, err
	}
	return model, props, nil
}
func getSettingShopPropData(env *game.Environment) (*orm.Model, []SettingShopProp, error) {
	var err error
	model, err := env.GetModel(SettingShopPropName)
	if err != nil {
		return nil, nil, err
	}
	var shopProps []SettingShopProp
	_, err = model.Query().Find(&shopProps)
	if err != nil {
		return nil, nil, err
	}
	return model, shopProps, nil
}
func (modelData *ModelData) GetDefineBuild(updateTime *time.Time) ([]*Build, error) {
	if updateTime != nil {
		builds := make([]*Build, 0, 5)
		for _, build := range modelData.BuildList {
			if build.HasUpdate(updateTime) {
				builds = append(builds, build)
			}
		}
		return builds, nil
	} else {
		return modelData.BuildList, nil
	}
}

func (modelData *ModelData) GetDefineUnit(updateTime *time.Time) ([]*Unit, error) {
	if updateTime != nil {
		units := make([]*Unit, 0, 5)
		for _, unit := range modelData.UnitList {
			if unit.HasUpdate(updateTime) {
				units = append(units, unit)
			}
		}
		return units, nil
	} else {
		return modelData.UnitList, nil
	}
}
func (modelData *ModelData) GetDefineNode(updateTime *time.Time) ([]*Node, error) {
	if updateTime != nil {
		nodes := make([]*Node, 0, 5)
		for _, node := range modelData.NodeList {
			if node.HasUpdate(updateTime) {
				nodes = append(nodes, node)
			}
		}
		return nodes, nil
	} else {
		return modelData.NodeList, nil
	}
}
func (modelData *ModelData) GetDefineItem(updateTime *time.Time) ([]*Item, error) {
	if updateTime != nil {
		items := make([]*Item, 0, 5)
		for _, item := range modelData.ItemList {
			if item.HasUpdate(updateTime) {
				items = append(items, item)
			}
		}
		return items, nil
	} else {
		return modelData.ItemList, nil
	}
}

func (modelData *ModelData) GetSettingDirect(updateTime *time.Time) ([]*Direct, error) {
	if updateTime != nil {
		items := make([]*Direct, 0, 5)
		for _, item := range modelData.DirectList {
			if item.HasUpdate(updateTime) {
				items = append(items, item)
			}
		}
		return items, nil
	} else {
		return modelData.DirectList, nil
	}
}
func (modelData *ModelData) GetSettingEquip(updateTime *time.Time) ([]*Equip, error) {
	if updateTime != nil {
		items := make([]*Equip, 0, 5)
		for _, item := range modelData.EquipList {
			if item.HasUpdate(updateTime) {
				items = append(items, item)
			}
		}
		return items, nil
	} else {
		return modelData.EquipList, nil
	}
}
func (modelData *ModelData) GetSettingPower(updateTime *time.Time) ([]*Item, error) {
	if updateTime != nil {
		items := make([]*Item, 0, 5)
		for _, item := range modelData.ItemList {
			if item.HasUpdate(updateTime) {
				items = append(items, item)
			}
		}
		return items, nil
	} else {
		return modelData.ItemList, nil
	}
}
func (modelData *ModelData) GetSettingScience(updateTime *time.Time, language string) ([]*Science, error) {
	if updateTime != nil {
		items := make([]*Science, 0, 5)
		for _, item := range modelData.ScienceList {
			if item.HasUpdate(updateTime) {
				items = append(items, item)
			}
		}
		return items, nil
	} else {
		return modelData.ScienceList, nil
	}
}
func (modelData *ModelData) GetSettingProp(updateTime *time.Time) ([]*Prop, error) {
	if updateTime != nil {
		items := make([]*Prop, 0, 5)
		for _, item := range modelData.PropList {
			if item.HasUpdate(updateTime) {
				items = append(items, item)
			}
		}
		return items, nil
	} else {
		return modelData.PropList, nil
	}
}

func (modelData *ModelData) DistinctDirect(directIds []int) []int {
	m := map[int]*Direct{}
	l := []int{}
	for _, id := range directIds {
		//fmt.Println("direct", id, modelData.DirectMap[id])
		direct := modelData.DirectMap[id]
		if direct.Define == 0 {
			l = append(l, direct.Id)
			continue
		}
		if g, ok := m[direct.Define]; !ok {
			m[direct.Define] = direct
		} else if g.DefineLevel < direct.DefineLevel {
			m[direct.Define] = direct
		}
	}
	for _, direct := range m {
		l = append(l, direct.Id)
	}
	return l
}
